package com.imooc.ecommerce.service.async;

import com.imooc.ecommerce.constant.AsyncTaskStatusEnum;
import com.imooc.ecommerce.vo.AsyncTaskInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 异步任务执行任务切面
 * @author zhangshao
 * @since 2023/11/30 21:47
 */
@Slf4j
@Aspect
@Component
public class AsyncTaskMonitor {
    /**
     * 注入异步任务执行管理器
     */
    @Autowired
    private AsyncTaskManager asyncTaskManager;

    /**
     * 异步任务执行的环绕切面
     * 环绕切面可以让我们在方法执行之前和执行之后 做一些 “额外”操作
     * @param proceedingJoinPoint
     * @return
     */
    @Around("execution(* com.imooc.ecommerce.service.async.AsyncServiceImpl.*(..))")
    public Object taskHandle(ProceedingJoinPoint proceedingJoinPoint){

        // 获取taskId,调用异步任务传入的第二个参数
        String taskId = proceedingJoinPoint.getArgs()[1].toString();

        // 获取任务信息,在提交任务的时间就已经放入到容器中了
        AsyncTaskInfo taskInfo = asyncTaskManager.getTaskInfo(taskId);
        log.info("AsyncTaskMonitor is monitoring async task :[{}]",taskId);

        taskInfo.setStatus(AsyncTaskStatusEnum.RUNNING);
        //设置为运行状态并重新加入容器
        asyncTaskManager.setTaskInfo(taskInfo);
        AsyncTaskStatusEnum status;
        Object result;

        try{
            // 执行异步任务
            result = proceedingJoinPoint.proceed();
            status = AsyncTaskStatusEnum.SUCCESS;
        }catch (Throwable ex){
            //异步任务出现了异常
            result = null;
            status = AsyncTaskStatusEnum.FAILED;
            log.error("AsyncTaskMonitor async task [{}] is failed,Error Info:[{}]",taskInfo,ex.getMessage(),ex);
        }

        // 设置异步任务其他信息, 并再次重新放入容器
        taskInfo.setEndTime(new Date());
        taskInfo.setStatus(status);
        taskInfo.setTotalTime(String.valueOf(taskInfo.getEndTime().getTime() - taskInfo.getStartTime().getTime()));
        asyncTaskManager.setTaskInfo(taskInfo);

        return result;
    }

}
